/* * * * * * * * * * * * * * * * * * * * * * * *
 * Author: Thanh Pham
 * Created on: May 3rd 2007
 * Last Modified by: 
 * Last Modified on:
 * 
 * * * * * * * * * * * * * * * * * * * * * * * */

using System;
using System.Linq;
using System.Data.Entity;
using System.Diagnostics;
using System.Security.Principal;
using System.Collections.Generic;
using Pharmacy.Data;
using Pharmacy.Ultilities;
using Pharmacy.Data.Entity;
using Pharmacy.Data.Repositories;




namespace Pharmacy.Business
{
	/// <summary>
	/// Process the business for the security (Authentication, Authorization) of the application.
	/// </summary>
    public class Security : BaseBusiness
	{
       
        public Security()
            : base() {            
        }
		/// <summary>
		/// Initializes a new instance of the <see cref="Security"/> class.
		/// </summary>
        public Security(IObjectContext context)
            : base(context)
		{
        }

        ///// <summary>
        ///// Check whether the current user exist in the database.
        ///// </summary>
        ///// <param name="userName">Name of the user.</param>
        ///// <param name="password">Password.</param>
        ///// <param name="appId">The application id user will be used.</param>
        ///// <returns>
        ///// The <see cref="DIS_User"/> object if the user login success or throw the <see cref="LoginFailException"/> if the user doesn't exist in the database
        ///// </returns>
        //public DIS_User Login(string userName, string password, int appId)
        //{
        //    PSession.DropCache();
        //    object obj = PSession.FindObject(typeof(DIS_User), 
        //                                new GroupOperator(GroupOperatorType.And,
        //                                                  new BinaryOperator("UserName", userName, BinaryOperatorType.Equal),
        //                                                  new BinaryOperator("Password", StringUtil.EncryptMD5(password), BinaryOperatorType.Equal),
        //                                                  new BinaryOperator("Enable", true, BinaryOperatorType.Equal),
        //                                                  new BinaryOperator("AppID", appId, BinaryOperatorType.Equal)));

        //    //if (obj == null)
        //    //{
        //    //    throw new LoginFailException(userName);
        //    //}
        //    return (DIS_User)obj;
        //}
        ///// <summary>
        ///// Creates the principal instance.
        ///// </summary>
        ///// <param name="userObj">The user object.</param>
        ///// <returns>The principal instance for the current thread</returns>
        //public GenericPrincipal CreatePrincipal(DIS_User userObj)
        //{
        //    GenericIdentity identity = new GenericIdentity(userObj.UserName, "OMS_CUSTOM_PRINCIPAL");
        //    GenericPrincipal principal = new GenericPrincipal(identity, GetAllowedFunctions(userObj.UserName));

        //    return principal;
        //}

	    /// <summary>
	    /// Gets the allowed functions for a user.
	    /// </summary>
	    /// <param name="userName">Name of the user.</param>
	    /// <returns>The string array of the allowed functions which the specific user has</returns>
	    /// <author></author>
	    /// <history>
        /// 2011.01.29 - ThangTran: quick fix for task #950: Update SecurityBO to make sure admin has unlimited rights, fixed Xml-doc.
	    /// </history>
	    private string[] GetAllowedFunctions(string userName)
		{
            //// --- Begin parameters checking code -----------------------------
            //Debug.Assert(!string.IsNullOrEmpty(userName));
            //// --- End parameters checking code -------------------------------

            //// ThangTran: quick fix for task #950
            //if (Global.CurrentUserIsAdmin)
            //{
            //    // current logging user is admin or in admin group, return all functions available in the system

            //    /*
            //     * from DIS_Function
            //     * where FunctionName is not empty
            //     * select distinct FunctionName
            //     * 
            //     * */

            //    return LinqToXpo
            //        .From<DIS_Function>(PSession)
            //        .AsEnumerable()
            //        .Where(delegate(DIS_Function t) { return !string.IsNullOrEmpty(t.FunctionName); })
            //        .Select<string>(delegate(DIS_Function t) { return t.FunctionName; })
            //        .Distinct()
            //        .ToArray();
            //}
            //else
            //{
            //    // return only functions in the PermissionAssignments
            //    // reuse code from ListPermissionAssignments(userName), possible full database foreach
            //    // rewrite from disabled code below

            //    /* 
            //     * from DIS_PermissionAssignment
            //     * where Function is not null and Function.FunctionName is not empty
            //     * select distinct Function.FunctionName
            //     * 
            //     * */

            //    return LinqToObject
            //        .From<DIS_PermissionAssignment>(ListPermissionAssignments(userName))
            //        .Where(delegate(DIS_PermissionAssignment t) { return t.Function != null && !string.IsNullOrEmpty(t.Function.FunctionName); })
            //        .Select<string>(delegate(DIS_PermissionAssignment t) { return t.Function.FunctionName; })
            //        .Distinct()
            //        .ToArray();
            //}            
            return new string[] { "" };
		}

        /// <summary>
        /// Gets list of functions that current logging user can use.
        /// </summary>
        /// <returns></returns>
        /// <author></author>
        /// <history>
        /// 2011.01.29 - ThangTran: quick fix for task #950: Update SecurityBO to make sure admin has unlimited rights, added Xml-doc.
        /// </history>
        public Function[] ListPermitedFunctions()
        {
            // ThangTran: quick fix for task #950
            if (Global.CurrentUserIsAdmin)
            {
                // current logging user is admin or in admin group, return all functions available in the system

                /*
                 * from DIS_Function
                 * where FunctionName is not empty
                 * select distinct *
                 * 
                 * */

                //return LinqToXpo
                //    .From<DIS_Function>(PSession)
                //    .AsEnumerable()
                //    .Where(delegate(DIS_Function t) { return !string.IsNullOrEmpty(t.FunctionName); })
                //    .Distinct()
                //    .ToArray();

                FunctionRepository rFunction = new FunctionRepository(PharmacyContext);
                return rFunction.AsQueryable()
                            .Where(delegate(Function t) { return !string.IsNullOrEmpty(t.Name); })
                            .Distinct()
                            .ToArray();
            }
            else
            {
                // return only functions in the PermissionAssignments
                // reuse code from ListPermissionAssignments(userName), possible full database foreach
                // rewrite from disabled code below

                /* 
                 * from DIS_PermissionAssignment
                 * where Function is not null and Function.FunctionName is not empty
                 * select distinct Function
                 * 
                 * */

                return LinqToObject
                    .From<PermissionAssignment>(ListPermissionAssignments(Global.UserName))
                    .Where(delegate(PermissionAssignment t) { return t.Function != null && !string.IsNullOrEmpty(t.Function.Name); })
                    .Select<Function>(delegate(PermissionAssignment t) { return t.Function; })
                    .Distinct()
                    .ToArray();                
            }            
            
        }
        
		/// <summary>
		/// Lists all the menus of the application.
		/// </summary>
		/// <returns>The collection of <see cref="DIS_Menu"/> object</returns>
		public List<Menu> ListAllMenus()
		{
            //return new XPCollection(PSession, typeof(Menu), 
            //                             new GroupOperator(GroupOperatorType.And, 
            //                                               new BinaryOperator("AppID", CurrentAppID, BinaryOperatorType.Equal),
            //                                               new InOperator("MenuType", new int[]{2, 3})), 
            //                             new SortProperty("MenuOrder", SortingDirection.Ascending));

            MenuRepository rMenu = new MenuRepository(PharmacyContext);
            return rMenu.AsQueryable()
                        .OrderBy(tmpMenu => tmpMenu.MenuOrder)
                        .ToList();

            return new List<Menu>();
		}

	    /// <summary>
	    /// Lists all the allowed menus on which the user has permission.
	    /// </summary>
	    /// <returns>The collection of <see cref="DIS_Menu"/> objects</returns>
	    /// <remarks>
	    /// The method will get the currently user in the principle of the thread
	    /// </remarks>
	    /// <author></author>
	    /// <history>
	    /// 2011.01.29 - ThangTran: quick fix for task #950: Update SecurityBO to make sure admin has unlimited rights.
	    /// </history>
	    public Menu[] ListPermitedMenus()
		{
            if (Global.CurrentUserIsAdmin)
            {
                // if current logging user is admin, allow him/her to use all menus

                /*
                 * from DIS_Function
                 * select distinct *
                 * 
                 * */

                //return LinqToXpo
                //    .From<DIS_Menu>(PSession)
                //    .AsEnumerable()
                //    .Distinct()
                //    .ToArray();           
                MenuRepository rMenu = new MenuRepository(PharmacyContext);
                return rMenu.AsQueryable()
                    .Distinct()
                    .ToArray();
            }
            else
            {
                // rewrite from old disabled code below
                /*
                 * from DIS_Menu
                 * where ID in 
                 * (
                 *      from ListPermissionAssignments(Global.UserName) 
                 *      select ID
                 * )
                 * 
                 * */

                //return LinqToXpo
                //    .From<Menu>(PSession)
                //    .In("ID",
                //        LinqToObject
                //            .From<PermissionAssignment>(ListPermissionAssignments(Global.UserName))
                //            .Select<int>(delegate(PermissionAssignment t) { return t.Menu.ID; })
                //            .ToArray()
                //    )
                //    .ToArray();   
                
                MenuRepository rMenu = new MenuRepository(PharmacyContext);
                List<PermissionAssignment> lstPermissionAssignment = ListPermissionAssignments(Global.UserName);
                List<int> lstPermissionMenuID = lstPermissionAssignment.Select(tmp => tmp.Menu.ID)
                                                                    .ToList();
                return rMenu.AsQueryable()
                    .Where(tmpMenu => lstPermissionMenuID.Contains(tmpMenu.ID))                    
                    .ToArray();                             
            }            
            
		}        

		/// <summary>
		/// Lists the roles which the current user belong to.
		/// </summary>
		/// <param name="userName">Name of the user.</param>
		/// <returns>The <see cref="XPCollection"/> object represent for the collection for <see cref="DIS_Role"/> objects</returns>
		public List<Role> ListRoles(string userName)
		{
            //XPCollection userRoles = new XPCollection(PSession, typeof(DIS_UserRole),
            //                                          new GroupOperator(GroupOperatorType.And,
            //                                                    new BinaryOperator("User.UserName", userName, BinaryOperatorType.Equal),
            //                                                    new BinaryOperator("User.AppID", CurrentAppID, BinaryOperatorType.Equal)));

            //int[] roleIds = new int[userRoles.Count];

            //for (int i = 0; i < userRoles.Count; i++)
            //{
            //    DIS_UserRole userRole = userRoles[i] as DIS_UserRole;
            //    roleIds[i] = userRole.Role.ID;
            //}
            //if (roleIds.Length > 0)
            //{
            //    return new XPCollection(PSession, typeof(DIS_Role), new InOperator("ID", roleIds));
            //}
            //else
            //{
            //    return new XPCollection(PSession, typeof(DIS_Role), false);
            //}

            UserRoleRepository rUserRole = new UserRoleRepository(PharmacyContext);
            List<int> lstRoleID = rUserRole.AsQueryable()
                                            .Where(tmpObject => tmpObject.User.UserName == userName)
                                            .Select(tmp => tmp.Role.ID )
                                            .ToList();

            if(lstRoleID != null && lstRoleID.Count > 0)
            {
                RoleRepository rRole = new RoleRepository(PharmacyContext);
                return rRole.AsQueryable()
                    .Where(tmp => lstRoleID.Contains(tmp.ID))
                    .ToList();
            }         
            return new List<Role>();
		}
		/// <summary>
		/// Lists the permission assignments for all roles of the current user.
		/// </summary>
		/// <param name="userName">Name of the user.</param>
		/// <returns>The <see cref="XPCollection"/> object represent for the collection of <see cref="DIS_PermissionAssignment"/> objects</returns>
		public List<PermissionAssignment> ListPermissionAssignments(string userName)
		{
            //XPCollection roles = ListRoles(userName);

            //int[] roleIds = new int[roles.Count];

            //for (int i = 0; i < roles.Count; i++)
            //{
            //    DIS_Role role = roles[i] as DIS_Role;
            //    roleIds[i] = role.ID;
            //}
            //if (roleIds.Length > 0)
            //{
            //    return new XPCollection(PSession, typeof(DIS_PermissionAssignment), new InOperator("Role.ID", roleIds));
            //}
            //else
            //{
            //    return new XPCollection(PSession, typeof(DIS_PermissionAssignment), false);
            //}
            //PermissionAssignmentRepository lstPermission = new PermissionAssignmentRepository(PharmacyContext);

            List<Role> rUserRole = ListRoles(userName);
            List<int> lstRoleID = rUserRole.Select(tmp => tmp.ID)
                                            .ToList();

            if (lstRoleID != null && lstRoleID.Count > 0)
            {
                PermissionAssignmentRepository rPermissionAssignment = new PermissionAssignmentRepository(PharmacyContext);
                return rPermissionAssignment.AsQueryable()
                    .Where(tmp => lstRoleID.Contains(tmp.Role.ID))
                    .ToList();
            }     
            return new List<PermissionAssignment>();
		}

        public List<Function> ListFunctionsByUserName(string userName)
        {
            //XPCollection userRoles = new XPCollection(PSession, typeof(DIS_UserRole),
            //                                          new GroupOperator(GroupOperatorType.And,
            //                                                    new BinaryOperator("User.UserName", userName, BinaryOperatorType.Equal),
            //                                                    new BinaryOperator("User.AppID", CurrentAppID, BinaryOperatorType.Equal)));

            //List<int> lstPerID = new List<int>();
            //foreach (DIS_UserRole userRole in userRoles)
            //{
            //    XPCollection pers = new XPCollection(PSession, typeof(DIS_PermissionAssignment),
            //       new BinaryOperator("Role.ID", userRole.Role.ID, BinaryOperatorType.Equal));

            //    if (pers == null)
            //        continue;
            //    foreach (DIS_PermissionAssignment per in pers)
            //    {
            //        if (per.Function == null) continue;
            //        lstPerID.Add(per.Function.ID);
            //    }   
            //}

            //XPCollection xp = new XPCollection(PSession, typeof(DIS_Function),
            //    new GroupOperator(GroupOperatorType.And,
            //        new BinaryOperator("AppID", CurrentAppID, BinaryOperatorType.Equal),
            //        new InOperator("ID", lstPerID)));

            //return xp;

            return LinqToObject.From<PermissionAssignment>(ListPermissionAssignments(userName))
                        .Where(delegate(PermissionAssignment t) { return t.Function != null && !string.IsNullOrEmpty(t.Function.Name); })
                        .Select<Function>(delegate(PermissionAssignment t) { return t.Function; })
                        .ToList();                             
        }        
	}
}
